﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SPLogger.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights reserved.
// </copyright>
// <summary>
//   Logger class that logs events to the SharePoint event log (ULS) and to the system event log.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace LifeInSharePoint.Common
{
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Reflection;
    using System.Security.Permissions;

#if SP2010
    using Microsoft.Practices.SharePoint.Common.Logging;
#else
    using Microsoft.Practices.SPG.Common.Logging;
#endif

    using Microsoft.SharePoint.Administration;
    using Microsoft.SharePoint.Security;

    using Microsoft.SharePoint;

    /// <summary>
    /// Logger class that logs events to the SharePoint event log (ULS) and to the system event log.
    /// </summary>
    [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
    public static class SPLogger
    {
        #region Constants and Fields

        /// <summary>
        /// The message prefix to be added to all logged messages.
        /// </summary>
        private const string MessagePrefix = Constants.ProductName + " : ";

        /// <summary>
        /// The logging category used by SP 2010
        /// </summary>
        private const string DefaultCategory = Constants.DefaultLoggingCategory;

        /// <summary>
        /// The default loggin area used by SP2010
        /// </summary>
        private const string DefaultArea = Constants.DefaultLoggingArea;

        /// <summary>
        /// Thge default event id used by the 2010 logger
        /// </summary>
        private const int DefaultEventId = 0;

        #endregion

        #region Public Methods

        /// <summary>
        /// Logs an exception to the SP ULS.
        /// </summary>
        /// <param name="ex">
        /// The exception to log.
        /// </param>
        public static void LogToDeveloper(Exception ex)
        {
            SPBaseLogger logger = new SPBaseLogger();
            logger.TraceToDeveloper(ex);
        }

        /// <summary>
        /// /// Logs an exception to the SP ULS.
        /// </summary>
        /// <param name="ex">
        /// The exception to log.
        /// </param>
        /// <param name="message">
        /// The message to log.
        /// </param>
        public static void LogToDeveloper(Exception ex, string message)
        {
            if (ex == null)
            {
                throw new ArgumentNullException("ex");
            }

            SPBaseLogger logger = new SPBaseLogger();
            Trace.WriteLine(MessagePrefix + message + ex.Message);
#if SP2010
            logger.TraceToDeveloper(ex, MessagePrefix + message, DefaultEventId, TraceSeverity.High, DefaultArea + "/" + DefaultCategory);
#else
            logger.TraceToDeveloper(ex, MessagePrefix + message);
#endif
        }

        /// <summary>
        /// Logs an exception to the SP ULS.
        /// </summary>
        /// <param name="ex">
        /// The exception to log.
        /// </param>
        /// <param name="message">
        /// The message to log.
        /// </param>
        /// <param name="args">
        /// The message arguments.
        /// </param>
        public static void LogToDeveloper(Exception ex, string message, params object[] args)
        {
            if (ex == null)
            {
                throw new ArgumentNullException("ex");
            }

            SPBaseLogger logger = new SPBaseLogger();
            string formattedMessage = String.Format(CultureInfo.InvariantCulture, message, args);
            Trace.WriteLine(MessagePrefix + formattedMessage + ex.Message);
#if SP2010
            logger.TraceToDeveloper(ex, MessagePrefix + formattedMessage, DefaultEventId, TraceSeverity.High, DefaultArea + "/" + DefaultCategory);
#else
            logger.TraceToDeveloper(ex, MessagePrefix + formattedMessage);
#endif
        }

        /// <summary>
        /// Logs a message to the SP ULS.
        /// </summary>
        /// <param name="message">
        /// The message to log.
        /// </param>
        /// <param name="traceSeverity">
        /// The trace severity.
        /// </param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Microsoft.Practices.SPG.Common.Logging.ILogger.TraceToDeveloper(System.String,Microsoft.SharePoint.Administration.TraceSeverity)", Justification = "Prefix does not need to be localisable")]
        public static void LogToDeveloper(string message, TraceSeverity traceSeverity)
        {
            SPBaseLogger logger = new SPBaseLogger();
            Trace.WriteLine(MessagePrefix + message);
#if SP2010
            logger.TraceToDeveloper(MessagePrefix + message, DefaultEventId, traceSeverity, DefaultArea + "/" + DefaultCategory);    
#else
            logger.TraceToDeveloper(MessagePrefix + message, traceSeverity);
#endif
        }

        /// <summary>
        /// Logs a message to the SP ULS.
        /// </summary>
        /// <param name="traceSeverity">
        /// The trace severity.
        /// </param>
        /// <param name="message">
        /// The message to log.
        /// </param>
        /// <param name="args">
        /// The message arguments.
        /// </param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Microsoft.Practices.SPG.Common.Logging.ILogger.TraceToDeveloper(System.String,Microsoft.SharePoint.Administration.TraceSeverity)", Justification = "Prefix does not need to be localisable")]
        public static void LogToDeveloper(TraceSeverity traceSeverity, string message, params object[] args)
        {
            SPBaseLogger logger = new SPBaseLogger();
            string formattedMessage = String.Format(CultureInfo.InvariantCulture, message, args);
            Trace.WriteLine(MessagePrefix + formattedMessage);
#if SP2010
            logger.TraceToDeveloper(MessagePrefix + formattedMessage, DefaultEventId, traceSeverity, DefaultArea + "/" + DefaultCategory);
#else
            logger.TraceToDeveloper(MessagePrefix + formattedMessage, traceSeverity);
#endif
        }

        /// <summary>
        /// Logs a message to the SP ULS.
        /// </summary>
        /// <param name="traceSeverity">
        /// The trace severity.
        /// </param>
        /// <param name="memberInfo">
        /// The methodBase object containing information about the calling method.
        /// </param>
        /// <param name="message">
        /// The message to log.
        /// </param>
        /// <param name="args">
        /// The message arguments.
        /// </param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Collaboris.Readership.Common.SPLogger.LogToDeveloper(Microsoft.SharePoint.Administration.TraceSeverity,System.String,System.Object[])", Justification = "Prefix does not need to be localisable")]
        public static void LogToDeveloper(TraceSeverity traceSeverity, MemberInfo memberInfo, string message, params object[] args)
        {
            if (memberInfo == null)
            {
                throw new ArgumentNullException("memberInfo");
            }

            LogToDeveloper(traceSeverity, MessagePrefix + String.Format(CultureInfo.CurrentCulture, "{0}:{1} - {2}", memberInfo.DeclaringType, memberInfo.Name, message), args);
        }

        /// <summary>
        /// The log to developer.
        /// </summary>
        /// <param name="traceSeverity">
        /// The trace severity.
        /// </param>
        /// <param name="memberInfo">
        /// MethodBase object providing information about the type that raised the exception.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Collaboris.Readership.Common.SPLogger.LogToDeveloper(Microsoft.SharePoint.Administration.TraceSeverity,System.String,System.Object[])", Justification = "Prefix does not need to be localisable")]
        public static void LogToDeveloper(TraceSeverity traceSeverity, MemberInfo memberInfo, string message)
        {
            if (memberInfo == null)
            {
                throw new ArgumentNullException("memberInfo");
            }

            LogToDeveloper(traceSeverity, MessagePrefix + String.Format(CultureInfo.CurrentCulture, "{0}:{1} - {2}", memberInfo.DeclaringType, memberInfo.Name, message));
        }

        /// <summary>
        /// The log to developer.
        /// </summary>
        /// <param name="additionalMessage">
        /// The additional message.
        /// </param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Microsoft.Practices.SPG.Common.Logging.ILogger.TraceToDeveloper(System.String)", Justification = "Prefix does not need to be localisable")]
        public static void LogToDeveloper(string additionalMessage)
        {
            SPBaseLogger logger = new SPBaseLogger();
            Trace.WriteLine(MessagePrefix + String.Format(CultureInfo.CurrentCulture, additionalMessage));
#if SP2010
            logger.TraceToDeveloper(MessagePrefix + additionalMessage, DefaultArea + "/" + DefaultCategory);
#else
            logger.TraceToDeveloper(MessagePrefix + additionalMessage);
#endif
        }

        /// <summary>
        /// The log to operations.
        /// </summary>
        /// <param name="ex">
        /// The exception.
        /// </param>
        public static void LogToOperations(Exception ex)
        {
            try
            {
                if (ex == null)
                {
                    throw new ArgumentNullException("ex");
                }

                SPBaseLogger logger = new SPBaseLogger();
                Trace.WriteLine(MessagePrefix + ex.Message);
                logger.LogToOperations(ex);
            }
            catch (Exception e)
            {
                LogToDeveloper(e);
                LogToDeveloper(ex);
            }
        }

        /// <summary>
        /// The log to operations.
        /// </summary>
        /// <param name="ex">
        /// The exception.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        public static void LogToOperations(Exception ex, string message)
        {
            try
            {
                if (ex == null)
                {
                    throw new ArgumentNullException("ex");
                }

                SPBaseLogger logger = new SPBaseLogger();
                Trace.WriteLine(MessagePrefix + message + ex.Message);
#if SP2010
                logger.LogToOperations(ex, MessagePrefix + message, DefaultEventId, EventLogEntryType.Error, DefaultArea + "/" + DefaultCategory);
#else
                logger.LogToOperations(ex, MessagePrefix + message);
#endif
            }
            catch (Exception e)
            {
                LogToDeveloper(e);
                LogToDeveloper(ex, message);
            }
        }

        /// <summary>
        /// The log to operations.
        /// </summary>
        /// <param name="ex">
        /// The exception.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="args">
        /// The message arguments.
        /// </param>
        public static void LogToOperations(Exception ex, string message, params object[] args)
        {

            string formattedMessage = string.Empty;
            try
            {
                if (ex == null)
                {
                    throw new ArgumentNullException("ex");
                }

                SPBaseLogger logger = new SPBaseLogger();
                formattedMessage = String.Format(CultureInfo.InvariantCulture, message, args);
                Trace.WriteLine(MessagePrefix + formattedMessage + ex.Message);
#if SP2010
                logger.LogToOperations(ex, MessagePrefix + formattedMessage, DefaultEventId, EventLogEntryType.Error, DefaultArea + "/" + DefaultCategory);                
#else
                logger.LogToOperations(ex, MessagePrefix + formattedMessage);
#endif
            }
            catch (Exception e)
            {
                LogToDeveloper(e);
                LogToDeveloper(ex, formattedMessage);
            }
        }

        /// <summary>
        /// Logs and exception to operations and details the name of the class and method where the exception ocurred
        /// </summary>
        /// <param name="exception">
        /// The exception.
        /// </param>
        /// <param name="className">
        /// Name of the class.
        /// </param>
        /// <param name="methodName">
        /// Name of the method.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="args">
        /// The message arguments.
        /// </param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Collaboris.Readership.Common.SPLogger.LogToOperations(System.Exception,System.String,System.Object[])", Justification = "MessagePrefix does not need to be localisable")]
        public static void LogToOperationsExtended(Exception exception, string className, string methodName, string message, params object[] args)
        {
            LogToOperations(exception, MessagePrefix + String.Format(CultureInfo.CurrentCulture, "{0}:{1} - {2}", className, methodName, message), args);
        }

        /// <summary>
        /// Logs and exception to operations and details the name of the class and method where the exception ocurred
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="className">Name of the class.</param>
        /// <param name="methodName">Name of the method.</param>
        /// <param name="message">The message.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Collaboris.Readership.Common.SPLogger.LogToOperations(System.Exception,System.String)", Justification = "MessagePrefix does not need to be localisable")]
        public static void LogToOperationsExtended(Exception exception, string className, string methodName, string message)
        {
            LogToOperations(exception, MessagePrefix + String.Format(CultureInfo.CurrentCulture, "{0}:{1} - {2}", className, methodName, message));
        }

        /// <summary>
        /// Logs and exception to operations and details the name of the class and method where the exception ocurred
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="className">The class name.</param>
        /// <param name="methodName">The method name.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Collaboris.Readership.Common.SPLogger.LogToOperations(System.Exception,System.String)", Justification = "MessagePrefix does not need to be localisable")]
        public static void LogToOperationsExtended(Exception exception, string className, string methodName)
        {
            if (exception == null)
            {
                throw new ArgumentNullException("exception");
            }

            LogToOperations(exception, MessagePrefix + String.Format(CultureInfo.CurrentCulture, "{0}:{1} - {2}", className, methodName, exception.Message));
        }

        #endregion
    }
}